<?php
//                            _ooOoo_
//                           o8888888o
//                           88" . "88
//                           (| -_- |)
//                            O\ = /O
//                        ____/`---'\____
//                      .   ' \\| |// `.
//                       / \\||| : |||// \
//                     / _||||| -:- |||||- \
//                       | | \\\ - /// | |
//                     | \_| ''\---/'' | |
//                      \ .-\__ `-` ___/-. /
//                   ___`. .' /--.--\ `. . __
//                ."" '< `.___\_<|>_/___.' >'"".
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |
//                 \ \ `-. \_ __\ /__ _/ .-` / /
//         ======`-.____`-.___\_____/___.-`____.-'======
//                            `=---='
//
//         .............................................
//                  佛祖镇楼                  BUG退散

namespace app\tool;


use app\LogHelper;
use Luler\Helpers\MultiProcessHelper;
use think\facade\Cache;
use think\facade\Validate;

class NginxLogTool
{
    /**
     * 推送nginx日志
     * @throws \Exception
     * @author 我只想看看蓝天 <1207032539@qq.com>
     */
    public static function work()
    {
        $base_path = config('app.nginx.path');
        $files = CommonTool::getAllFiles($base_path);
        $files = array_filter($files, function ($value) {
            if (preg_match('/\.log$/', $value)) {
                return true;
            }
            return false;
        });

        foreach ($files as $file) {
            MultiProcessHelper::instance()->multiProcessTask(function () use ($file) {
                $cache_key = 'NginxLogTool:work:' . md5($file);
                $since_count = Cache::get($cache_key) ?: 0;
                $handle = fopen($file, 'r');
                $i = 0;
                $months = [
                    'Jan' => '01',
                    'Feb' => '02',
                    'Mar' => '03',
                    'Apr' => '04',
                    'May' => '05',
                    'Jun' => '06',
                    'Jul' => '07',
                    'Aug' => '08',
                    'Sep' => '09',
                    'Oct' => '10',
                    'Nov' => '11',
                    'Dec' => '12',
                ];
                $methods = ['GET', 'POST', 'PATCH', 'DELETE', 'PUT', 'OPTIONS', 'HEAD', 'TRACE', 'CONNECT',];
                $data = [];
                while (!feof($handle)) {
                    $line = fgets($handle);
                    if ($line === false) {
                        continue;
                    }
                    if ($since_count <= $i) {
                        $param = [
                            'message' => $line,
                            'other' => $file,
                            'code' => '',
                            'waste_time' => 0,
                            'client_ip' => '',
                            'url' => '',
                            'create_time' => '',
                        ];
                        $level = LogHelper::$level_info;
                        $line = explode(' ', $line);
                        foreach ($line as $key => $value) {
                            $value = trim($value, '[]"');
                            if (empty($param['client_ip']) && Validate::is($value, 'ip')) {
                                $param['client_ip'] = $value;
                                continue;
                            }
                            if (empty($param['url']) && in_array($value, $methods)) {
                                $param['url'] = $line[$key + 1];
                                continue;
                            }
                            if (empty($param['code']) && is_numeric($value) && $value >= 100 && $value < 600) {
                                $param['code'] = $value;
                                if ($param['code'] >= 300 && $param['code'] < 500) {
                                    $level = LogHelper::$level_warning;
                                } elseif ($param['code'] >= 500) {
                                    $level = LogHelper::$level_error;
                                }
                                continue;
                            }
                            if (empty($param['create_time']) && preg_match('/(\d+)\/(\w+)\/(\d+):([\d:]+)/', $value, $match)) {
                                $param['create_time'] = $match[3] . '-' . ($months[$match[2]] ?? '00') . '-' . $match[1] . ' ' . $match[4];
                            }
                        }
                        //添加日志
                        $data[] = [
                            'level' => $level,
                            'client_ip' => $param['client_ip'],
                            'message' => $param['message'],
                            'other' => $param['other'],
                            'create_time' => $param['create_time'],
                            'url' => $param['url'],
                            'waste_time' => $param['waste_time'],
                            'code' => $param['code'],
                        ];
                        if (count($data) >= 100) {
                            LogHelper::instance()->saveLog($data);
                            Cache::inc($cache_key, count($data));
                            $data = [];
                        }
                    }
                    $i++;
                }
                if (!empty($data)) {
                    LogHelper::instance()->saveLog($data);
                    Cache::inc($cache_key, count($data));
                }
                fclose($handle);
            });
        }
    }
}